﻿/************************************************************************/
/* Name ：       简单数据数组模版类
/* Description : 数组大小动态增加，可以设定初始大小
/* Note :        只能实现可以通过“==”进行对比且可以通过“=”赋值的数据类型
/* Author :      Victor
/* Crete Time :  2014.6.16
/************************************************************************/
#pragma once

#include "../EUILib.h"

template <typename T> 
class CDataArray
{
public:
	/************************************************************************/
	/*  initialSize : 初始数组大小
	/*　bEnableOrder ：是否保持顺序
	/************************************************************************/
	CDataArray(UINT initialSize = 32, BOOL bEnableOrder = FALSE);
	
	~CDataArray( );

public:

	/************************************************************************/
	/* 获取数组中数据的个数
	/************************************************************************/
	UINT GetSize(void) const;

	/************************************************************************/
	/* 添加一个数据项到数组中
	/************************************************************************/
	BOOL Add(const T& items);

	/************************************************************************/
	/* 根据序列号Index删除一个数据
	/************************************************************************/
	BOOL RemoveAt(UINT index);

	/************************************************************************/
	/* 根据数值删除数据，删除数组中所有的数据值等于参数items的数据，可能删除多项
	/************************************************************************/
	BOOL Remove(T& items);

	/************************************************************************/
	/* 查找指定数据项, 如果找到该数据项则返回相应的index，否则返回-1
	/************************************************************************/
	int Find(T& items);

	/************************************************************************/
	/* 根据索引值修改数组中的对应数据项，index必须在有效范围内才能执行成功
	/************************************************************************/
	BOOL SetAt(UINT index, const T& items);

	/************************************************************************/
	/* 清空数组
	/************************************************************************/
	void Clear(void);

	/************************************************************************/
	/* 运算符重载，更加index获取数据值
	/************************************************************************/
	T& operator [] (UINT index) const;

	/************************************************************************/
	/* 设置是否保持顺序
	/* bOrder为TRUE时，数组保持插入顺序，删除其中数据后其他数据任保持之前顺序
	/* bOrder为FALSE时，数组保持插入顺序，删除时会调整数据的顺序
	/************************************************************************/
	void SetEnableOrder(BOOL bOrder);

private:

	/************************************************************************/
	/* 模版数组指针
	/************************************************************************/
	T*   m_pList;

	/************************************************************************/
	/* 数组的使用容量
	/************************************************************************/
	UINT m_uCount;

	/************************************************************************/
	/* 数组的总容量
	/************************************************************************/
	UINT m_uSize;

	/************************************************************************/
	/* 是否保持顺序标志
	/************************************************************************/
	BOOL m_bEnableOrder;
};

template <typename T>
CDataArray<T>::CDataArray(UINT initialSize /* = 32*/, BOOL bEnableOrder /*= FALSE*/) : m_pList(NULL), m_uCount(0)
{
	UINT size = initialSize > 8 ? initialSize : 8 ;
	m_uSize = size;

	m_pList = static_cast<T*>(malloc( sizeof(T) * m_uSize ));

	m_bEnableOrder = bEnableOrder;
}

template <typename T>
CDataArray<T>::~CDataArray()
{
	Clear();
}

template <typename T>
T& CDataArray<T>::operator[]( UINT index ) const
{
	if(index < 0 || index >= m_uCount)
	{
		RaiseException( (DWORD)EXCEPTION_ARRAY_BOUNDS_EXCEEDED, EXCEPTION_NONCONTINUABLE, 0, NULL );
	}

	return m_pList[index];
}

template <typename T>
void CDataArray<T>::Clear( void )
{
	if(m_pList != NULL)
	{
		free(m_pList);
		m_pList = NULL;
		m_uSize = 0;
		m_uCount = 0;
	}
}

template <typename T>
BOOL CDataArray<T>::SetAt( UINT index, const T& items )
{
	if(index < 0 || index >= m_uCount) return FALSE;

	m_pList[index] = items;
}

template <typename T>
BOOL CDataArray<T>::Remove( T& items )
{
	for(UINT i = 0; i < m_uCount; i++)
	{
		if(items == m_pList[i])
		{
			RemoveAt(i); 
		}
	}

	return TRUE;
}

template <typename T>
int CDataArray<T>::Find( T& items )
{
	for(UINT i = 0; i < m_uCount; i++)
	{
		if(items == m_pList[i])
		{
			return i;
		}
	}

	return -1;
}

template <typename T>
BOOL CDataArray<T>::RemoveAt( UINT index )
{
	if(index < 0 || index >= m_uCount)  return FALSE;

	if(index < --m_uCount)
	{
		if(m_bEnableOrder)
		{
			memmove(m_pList + index, m_pList + index + 1, m_uCount - index);
		}
		else
		{
			m_pList[index] = m_pList[m_uCount];
		}
	}

	return TRUE;
}

template <typename T>
BOOL CDataArray<T>::Add( const T& items )
{
	if( ++m_uCount >= m_uSize)
	{
		int reSize = m_uSize * 2;
		T* pArray = static_cast<T*>(realloc(m_pList, sizeof(T) * reSize));
		if(pArray != NULL)
		{
			m_uSize = reSize;
			m_pList = pArray;
		}
		else
		{
			m_uCount--;
			return FALSE;
		}
	}
	m_pList[m_uCount - 1] = items;

	return TRUE;
}

template <typename T>
UINT CDataArray<T>::GetSize( void ) const
{
	return m_uCount;
}

template <typename T>
void CDataArray<T>::SetEnableOrder( BOOL bOrder )
{
	m_bEnableOrder = bOrder;
}

